import { toolPlusButton, toolMinusButton } from './nodes.js'

export const EVENT_SELECTED_NODE = 'event:selected:node'
export const EVENT_ADD_NODE = 'event:add:node'
export const EVENT_REMOVE_NODE = 'event:remove:node'
export const EVENT_MOVE_NODE = 'event:move:node'
export const EVENT_REMOVE_EDGE = 'event:remove:edge'
export const EVENT_EDGE_CONNECTION = 'event:edge:connection'

export default function registerEvent(graph) {
  // 控制连接桩显示/隐藏
  const showPorts = (ports, show) => {
    for (let i = 0, len = ports.length; i < len; i += 1) {
      ports[i].style.visibility = show ? 'visible' : 'hidden'
    }
  }
  graph.on('node:mouseenter', () => {
    const container = document.getElementById('graph-container')
    const ports = container.querySelectorAll('.x6-port-body')
    showPorts(ports, true)
  })
  graph.on('node:mouseleave', () => {
    const container = document.getElementById('graph-container')
    const ports = container.querySelectorAll('.x6-port-body')
    showPorts(ports, false)
  })
  // #endregion

  // 节点拖入后自动添加连线
  function autoAddEdge(cell, node) {
    let area = graph.getCellsBBox([cell])
    area = {
      x: area.x - 50,
      y: area.y - 100,
      width: area.width + 50,
      height: area.height + 100,
    }
    let nodes = graph.getNodesInArea(area)
    nodes = nodes.filter((item) => item.id !== node.id)

    if (nodes.length) {
      let parentNode = nodes[0]
      graph.addEdge({
        source: {
          cell: parentNode.id,
          port: parentNode.ports.items.find((item) => item.group == 'bottom')
            .id,
        },
        target: {
          cell: node.id,
          port: node.ports.items.find((item) => item.group == 'top').id,
        },
      })
    }
  }

  function changeChildrenVisible(node, visible) {
    const succ = graph.getSuccessors(node, { distance: 1 })
    if (succ) {
      succ.forEach((node) => {
        node.setVisible(visible)
        if (visible && graph.getSuccessors(node, {distance: 1}).length > 0) {
          nodeAddExtend(node, false)
        } else {
          node.removeTool('button')
        }
        changeChildrenVisible(node, visible)
      })
    }
  }

  function nodeAddExtend(node, isPlus) {
    node.removeTool('button')
    node.addTools({
      name: 'button',
      args: {
        markup: isPlus ? toolPlusButton :  toolMinusButton,
        x: '100%',
        y: '50%',
        onClick: isPlus ? toolPlusClick : toolMinusClick
      }
    })
  }

  function toolMinusClick({cell}) {
    changeChildrenVisible(cell, false)
    nodeAddExtend(cell, true)
    cell.data.extendStatus = false
  }

  function toolPlusClick({ cell }) {
    changeChildrenVisible(cell, true)
    nodeAddExtend(cell, false)
    cell.data.extendStatus = true
  }

  function changeNodeCollapseTool(node) {
    try {
      let outNodes = graph.getNeighbors(node, { incoming: false, outgoing: true })
      if (outNodes.length > 0) {
        nodeAddExtend(node, false)
      } else {
        node.removeTool('button')
      }
    } catch(err) {
      console.log(err)
    }
  }

  function getSortNodes(node) {
    window.xxNode = node
    const parentNode = graph.getNeighbors(node, { incoming: true, outgoing: false })
    if(parentNode.length > 0) {
      let outNodes = graph.getNeighbors(parentNode[0], { incoming: false, outgoing: true })
      if (outNodes.length > 0) {
        outNodes.sort((a, b) => a.position().x - b.position().x)
        return {
          parentId: parentNode[0].id,
          nodeIds: outNodes.map(item => item.id)
        }
      }
    }

    return {}
  }

  graph.on('node:added', (event) => {
    graph.emit(EVENT_ADD_NODE, event)
  })

  graph.on('edge:added', (event) => {
    if (!event.edge.target.cell) {
      return
    }
    const { edge } = event
    const sourceCell = graph.getCellById(edge.source.cell)
    changeNodeCollapseTool(sourceCell)
  })

  graph.on('edge:connected', (event) => {
    graph.emit(EVENT_EDGE_CONNECTION, event)
    if (!event.edge.target.cell) {
      return
    }
    const { edge } = event
    const sourceCell = graph.getCellById(edge.source.cell)
    changeNodeCollapseTool(sourceCell)

    let eventData = getSortNodes(sourceCell)
    if (eventData.nodeIds && eventData.nodeIds.length > 0) {
      graph.emit(EVENT_MOVE_NODE, eventData)
    }
  })

  graph.on('edge:removed', (event) => {
    const { edge } = event
    const sourceCell = graph.getCellById(edge.source.cell)
    changeNodeCollapseTool(sourceCell)
    graph.emit(EVENT_REMOVE_EDGE, event)
  })

  graph.on('node:removed', (event) => {
    graph.emit(EVENT_REMOVE_NODE, event)
    // 自定义事件触发
    graph.emit(EVENT_SELECTED_NODE, null)
  })

  graph.on('node:click', ({ node }) => {
    // 自定义事件触发
    graph.emit(EVENT_SELECTED_NODE, node)
  })

  graph.on('node:moved', ({node}) => {
    let eventData = getSortNodes(node)
    graph.emit(EVENT_MOVE_NODE, eventData)
  })
}
